package com.gb.web.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * xml解析工具类
 * 
 */
public class XmlParseUtil {

	/**
	 * 根据标签名查看是否含有某个标签的标签体
	 * 
	 * @param labelName 标签名
	 * @return
	 */
	private static boolean isContainLabName(String labelStr,String labelName) {
		if (labelStr == null) {
			return false;
		}
		labelStr = labelStr.trim();
		int length = labelStr.length();
		if (length <= 0) {
			return false;
		}
		int startIndex = labelStr.indexOf("<"+ labelName+" ");
		int endIndex = labelStr.indexOf("</" + labelName+">");
		int endLabelIndex = labelStr.indexOf("/>");
		if (startIndex >=0 && ((endLabelIndex<=length && endLabelIndex >0)||(endIndex>0 && endIndex <=length)) ) {
			return true;
		}
		return false;
	}
	
	/**
	 * 从xml字符串中根据标签名 获取标签字符串
	 * 
	 * @param xmlStr
	 * @param labelName
	 * @return
	 */
	private static List<String> getLabelStrLst(String xmlStr, String labelName) {
		String [] xmlStrArr = xmlStr.split("\n");
		List <String> xmlStrLst = Arrays.asList(xmlStrArr);
		List<String> labelStrLst = new ArrayList<String> ();
		for (String labelStr : xmlStrLst) {
			if (isContainLabName(labelStr, labelName)) {
				labelStrLst.add(labelStr.trim());
			}
		}
		return labelStrLst;
	}
	
	/**
	 * 根据xml片段获取 某个标签的所有属性及其对应字符串
	 * @param xmlStr  xml片段字符串 或者xml字符串
	 * @param labelName 标签名
	 * @return
	 */
	private static List<Map<String,String>> getKeyValMapLstByXmlStrAndLabelName(String xmlStr,String labelName) {
		List<Map<String,String>> keyValMapLst = new ArrayList<Map<String,String>>();
		List<String> labelStrLst = getLabelStrLst(xmlStr, labelName);
		Map<String,String> keyValMap = null;
		for (String labelStr : labelStrLst) {
			keyValMap = getKeyValOfXmlStr(labelStr);
			keyValMapLst.add(keyValMap);
		}
		return keyValMapLst;
	}
	
	/**
	 * 根据文件名 和 标签名 在xml文件中获取所有标签内的键值对字符串
	 * 
	 * @param fileName 文件名
	 * @param labelName 标签名
	 * @return
	 * @throws Exception
	 */
	private static List<Map<String,String>> getKeyValMapLstByFileNameAndLabelName(String fileName,String labelName) throws Exception {
		String xmlStr = readFile(fileName);
		List<Map<String,String>> mapLst = getKeyValMapLstByXmlStrAndLabelName(xmlStr, labelName);
		return mapLst;
	}
	
	/**
	 * 根据文件路径 和 标签名 在xml文件中获取所有标签内的键值对字符串
	 * @param filePath 文件路径 
	 * @param labelName 文件名
	 * @return
	 * @throws Exception
	 */
	public static List<Map<String,String>> getKeyValMapLstByFilePathAndLabelName(String filePath,String labelName) throws Exception {
		String fileName = getProjectPath(filePath);
		List<Map<String,String>> mapLst = getKeyValMapLstByFileNameAndLabelName(fileName,labelName);
		return mapLst;
	}
	

	/**
	 * 读取文件内容
	 * @param path 文件在项目中的路径
	 * @return
	 * @throws Exception
	 */
    public static String readFile(String path) throws Exception {
        File file=new File(path);
        FileInputStream fis = new FileInputStream(file);
        FileChannel fc = fis.getChannel();
        ByteBuffer bb = ByteBuffer.allocate(new Long(file.length()).intValue());
        //fc向buffer中读入数据
        fc.read(bb);
        bb.flip();
        String str=new String(bb.array(),"UTF8");
        fc.close();
        fis.close();
        return str;
    }
    
    
    /**
	 * 根据相对路劲获取绝对路劲
	 * @param relative
	 * @return
	 */
	public static String getProjectPath(String relativePath) {
		try {
			String absolutePath = "";
			if (relativePath == null || "".equals(relativePath.trim())) {
				absolutePath = getRootPath();
			} else {
				if (relativePath.trim().indexOf("/") != 0) {
					relativePath = "/" + relativePath.trim();
				}
				absolutePath =  XmlParseUtil.class.getResource(relativePath).getPath();
			}
			return absolutePath;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取项目根路径
	 * @return
	 */
	public static String getRootPath() {
		try {
			String rootPath = getProjectPath("/");
			return rootPath;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	  /**
     * 通过xmlStr 获取满足正则表达式的结果 并存入map中
     * @param xmlStr
     * @return  能够匹配上的xml字符串
     */
	public static final String XML_KEY_VALUE_STRING = "(([\\w]+[\\s]*)=([\\s]*\"[([\\w\\s_\\.-]*[\u4e00-\u9fa5]*)]*\"[\\s]*))";
    public static Map<String ,String> getKeyValOfXmlStr(String xmlStr) {
		Map<String,String> attrMap =  new HashMap<String,String>();
		Pattern p=Pattern.compile(XML_KEY_VALUE_STRING); 
		Matcher m=p.matcher(xmlStr); 
		String group = null;
		String key = null;
		String val = null;
		while(m.find()) { 
			group = m.group();
			key = group.substring(0, group.indexOf("="));
			val = group.substring(group.indexOf("\"")+1, group.lastIndexOf("\""));
			attrMap.put(key, val);
		}
		return attrMap;
	}
	
	public static void main(String[] args) {
		try {
			List<Map<String,String>> mapLst = getKeyValMapLstByFilePathAndLabelName("xml/commodityConfig.xml", "commodityConfig");
			System.out.println(mapLst);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
